﻿//
// Created by 67376 on 2022/12/30.
//
#include <string.h>
#include "xframe.h"
// #include "notify.h"
// #include "mj_des.h"
#include <stddef.h>
#include <time.h>
#include <string.h>
// #include "factory.h"
// #include "network.h"

// #define LOG_TAG "xframe"
// #define LOG_LVL LOG_LVL_DBG
// #include "ulog.h"
// #include "xsys.h"

//
// static int encode_int32_t(unsigned char *buffer, int size, int pos, const int32_t *value, int len) {
//    if (pos + sizeof(int32_t) > size) {
//        return -1;
//    }
//
//    int32_t v = *value;
//
//    buffer[pos + 0] = (v >> 24) & 0xff;
//    buffer[pos + 1] = (v >> 16) & 0xff;
//    buffer[pos + 2] = (v >> 8) & 0xff;
//    buffer[pos + 3] = v & 0xff;
//
//    return 4;
//}
//
// static int decode_int32_t(const unsigned char *buffer, int size, int pos, int32_t *value, int len) {
//    if (pos + sizeof(int32_t) > size) {
//        return -1;
//    }
//
//    *value = (buffer[pos + 0] << 24) | (buffer[pos + 1] << 16) | (buffer[pos + 2] << 8) | buffer[pos + 3];
//
//    return 4;
//}
//
// static int encode_int16_t(unsigned char *buffer, int size, int pos, const int16_t* value, int len) {
//    if (pos + sizeof(int16_t) > size) {
//        return -1;
//    }
//
//    int16_t v = *value;
//
//    buffer[pos + 0] = (v >> 8) & 0xff;
//    buffer[pos + 1] = v & 0xff;
//
//    return 2;
//}
//
// static int decode_int16_t(const unsigned char *buffer, int size, int pos, int16_t *value, int len) {
//    if (pos + sizeof(int16_t) > size) {
//        return -1;
//    }
//
//    *value = (short)((buffer[pos + 0] << 8) | buffer[pos + 1]);
//
//    return 2;
//}
//
// static int encode_int18_t(unsigned char *buffer, int size, int pos, const int8_t* value, int len) {
//    if (pos + sizeof(int8_t) > size) {
//        return -1;
//    }
//
//    buffer[pos] = *value;
//
//    return 1;
//}
//
// static int decode_int8_t(const unsigned char *buffer, int size, int pos, int8_t *value, int len) {
//    if (pos + sizeof(int8_t) > size) {
//        return -1;
//    }
//
//    *value = (char)buffer[pos];
//
//    return 1;
//}

static int encode_x32(unsigned char *buffer, int size, int pos, const uint32_t *value, int len)
{
    if (pos + 4 > size)
    {
        return -1;
    }

    uint32_t v = *value;

    buffer[pos + 0] = (v >> 24) & 0xff;
    buffer[pos + 1] = (v >> 16) & 0xff;
    buffer[pos + 2] = (v >> 8) & 0xff;
    buffer[pos + 3] = v & 0xff;

    return pos + 4;
}

static int decode_x32(const unsigned char *buffer, int size, int pos, uint32_t *value, int len)
{
    if (pos + 4 > size)
    {
        return -1;
    }

    *value = (buffer[pos + 0] << 24) | (buffer[pos + 1] << 16) | (buffer[pos + 2] << 8) | buffer[pos + 3];

    return pos + 4;
}

static int encode_x16(unsigned char *buffer, int size, int pos, const uint16_t *value, int len)
{
    if (pos + 2 > size)
    {
        return -1;
    }

    uint16_t v = *value;

    buffer[pos + 0] = (v >> 8) & 0xff;
    buffer[pos + 1] = v & 0xff;

    return pos + 2;
}

static int decode_x16(const unsigned char *buffer, int size, int pos, uint16_t *value, int len)
{
    if (pos + 2 > size)
    {
        return -1;
    }

    *value = (buffer[pos + 0] << 8) | buffer[pos + 1];

    return pos + 2;
}

static int encode_x8(unsigned char *buffer, int size, int pos, const uint8_t *value, int len)
{
    if (pos + 1 > size)
    {
        return -1;
    }

    buffer[pos] = *value;

    return pos + 1;
}

static int decode_x8(const unsigned char *buffer, int size, int pos, uint8_t *value, int len)
{
    if (pos + 1 > size)
    {
        return -1;
    }

    *value = buffer[pos];

    return pos + 1;
}

// static int decode_u24(const unsigned char *buffer, int size, int pos, uint32_t *value, int len) {

//    if (pos + 3 > size) {
//        return -1;
//    }

//    *value = (buffer[pos + 0] << 16) | (buffer[pos + 1] << 8) | buffer[pos + 2];

//    return 3;
//}

static int encode_x24(unsigned char *buffer, int size, int pos, const uint32_t *value, int len)
{

    if (pos + 3 > size)
    {
        return -1;
    }

    uint32_t v = *value;

    buffer[pos + 0] = (v >> 16) & 0xff;
    buffer[pos + 1] = (v >> 8) & 0xff;
    buffer[pos + 2] = v & 0xff;

    return pos + 3;
}

static int encode_c_str(unsigned char *buffer, int size, int pos, const char *value, int len)
{
    if (value == NULL)
    {
        return -1;
    }

    uint8_t s = strlen(value);

    if (pos + s + 1 > size)
    {
        return -1;
    }

    buffer[pos + 0] = s;

    if (s > 0)
        memcpy(buffer + pos + 1, value, s);

    return pos + s + 1;
}

static int decode_c_str(const unsigned char *buffer, int size, int pos, char *value, int len)
{

    uint8_t s = 0;

    if ((pos = decode_x8(buffer, size, pos, &s, sizeof(uint8_t))) < 0)
    {
        return -1;
    }

    if (pos + s > size)
    {
        return -1;
    }

    if (s == 0)
    {
        value[0] = '\0';
    }
    else
    {
        memcpy(value, buffer + pos, s);
        value[s] = '\0';
    }

    return pos + s;
}

static int encode_c_arr(unsigned char *buffer, int size, int pos, const void *value, int len)
{
    if (value == NULL)
    {
        return -1;
    }

    uint8_t s = *(uint8_t *)value;
    const uint8_t *data = (const uint8_t *)value + sizeof(uint8_t);

    if (pos + s > size)
    {
        return -1;
    }

    memcpy(buffer + pos, data, s);

    return pos + s;
}

// static int decode_c_arr(const unsigned char *buffer, int size, int pos, void *value, int len) {
//     if (pos >= size) {
//         return -1;
//     }
//     int ret = 0;
//     uint8_t *s = (uint8_t*)value;
//     if ((ret = decode_x8(buffer, size, pos, s, len)) < 0) {
//         return -1;
//     }

//    if (pos + *s + ret > size) {
//        return -1;
//    }

//    uint8_t *data = (uint8_t*)value + sizeof(uint8_t);

//    memcpy(data, buffer + pos + ret, *s);

//    return ret + (int)*s;
//}

static int decode_s_arr(const unsigned char *buffer, int size, int pos, char *value, int len)
{

    if (pos + len > size)
    {
        return -1;
    }

    memcpy(value, buffer + pos, len);

    return pos + len;
}

static int encode_s_arr(unsigned char *buffer, int size, int pos, const void *value, int len)
{

    if (pos + len > size)
    {
        return -1;
    }

    memcpy(buffer + pos, value, len);

    return pos + len;
}

static int encode_c_time(unsigned char *buffer, int size, int pos, const void *value, int len)
{
    uint32_t t = *(uint32_t *)value;

    // uint8_t is_tick_time = 0;

    ////check the high 1 bit if is 1
    // if(t & 0x80000000) {
    //     is_tick_time = 1;

    //    //clear the high 1 bit
    //    t &= 0x7fffffff;
    //}

    // if(is_tick_time) {
    //     //cover to real time
    //     if(t < rt_tick_get()) {
    //         t = time(NULL) - (rt_tick_get() - t) / RT_TICK_PER_SECOND;
    //         LOG_I("fix time %d", t);
    //     } else {
    //         //直接用当前时间填充
    //         t = time(NULL);
    //     }
    // }

    // if(t < XSYS_UTC_MIN_VALUE || t > XSYS_UTC_MAX_VALUE) {
    //     //丢掉该数据
    //     LOG_E("time out of range %d", t);
    // }

    return encode_x32(buffer, size, pos, &t, len);
}

static int encode_c_encode(unsigned char *buffer, int size, int pos, const void *value, int len)
{
    c_encode *obj = (c_encode *)value;
    if (obj == NULL)
    {
        return -1;
    }

    if ((pos = (*obj)(buffer, size, pos)) < 0)
    {
        return -1;
    }

    return pos;
}

static int encode_gps_t(unsigned char *buffer, int size, int pos, const void *value, int len)
{

    const gps_t *obj = (const gps_t *)value;

    //    buf_write_u32(buf, obj->time); // 定时时间
    //
    //    buf_write_bit(buf, 7, 1, obj->src);        // 定位来源
    //    buf_write_bit(buf, 6, 1, obj->valid);      // 数据有效性
    //    buf_write_bit(buf, 5, 1, obj->f_lng);      // 东西经
    //    buf_write_bit(buf, 4, 1, obj->f_lat);      // 南北纬
    //    buf_write_bit(buf, 0, 4, obj->satellites); // 定位卫星个数
    //
    //    buf->len += 1;
    //
    //    uint32_t height = (uint32_t) (obj->height) + 10000;
    //
    //    buf_write_u16(buf, (height << 1) | ((obj->lon >> 24) & 0x01));
    //
    //    buf_write_u24(buf, obj->lon & 0x00ffffff);
    //    buf_write_u24(buf, obj->lat & 0x00ffffff);
    //    buf_write_u16(buf, obj->speed << 4 | ((obj->direction >> 8) & 0x03));
    //    buf_write_u8(buf, obj->direction & 0xff);
    //
    //    buf_write_u16(buf, obj->pdod << 4 | ((obj->hdop >> 8) & 0x04));
    //    buf_write_u8(buf, obj->hdop & 0xff);
    //
    //    buf_write_u16(buf, (obj->vdop << 4) | (obj->ign_status << 2) | (obj->is_turn_point ? 1 : 0) << 1);
    //
    //    buf_write_u16(buf, obj->hacc);
    //
    //    buf_write_u8(buf, 0x00);

    if ((pos = encode_x32(buffer, size, pos, &obj->time, sizeof(obj->time))) < 0)
    {
        return -1;
    }

    uint8_t tmp = 0;
    tmp |= obj->src << 7;
    tmp |= obj->valid << 6;
    tmp |= obj->f_lng << 5;
    tmp |= obj->f_lat << 4;
    tmp |= (obj->satellites > 15) ? 15 : obj->satellites;
    if ((pos = encode_x8(buffer, size, pos, &tmp, sizeof(tmp))) < 0)
    {
        return -1;
    }

    uint32_t height = (uint32_t)(obj->height) + 10000;
    uint16_t tmp2 = (height << 1) | ((obj->lon >> 24) & 0x01);
    if ((pos = encode_x16(buffer, size, pos, &tmp2, sizeof(tmp2))) < 0)
    {
        return -1;
    }

    uint32_t tmp3 = obj->lon & 0x00ffffff;
    if ((pos = encode_x24(buffer, size, pos, &tmp3, sizeof(tmp3))) < 0)
    {
        return -1;
    }

    uint32_t tmp4 = obj->lat & 0x00ffffff;
    if ((pos = encode_x24(buffer, size, pos, &tmp4, sizeof(tmp4))) < 0)
    {
        return -1;
    }

    uint16_t tmp5 = obj->speed << 4 | ((obj->direction >> 8) & 0x03);
    if ((pos = encode_x16(buffer, size, pos, &tmp5, sizeof(tmp5))) < 0)
    {
        return -1;
    }

    uint8_t tmp6 = obj->direction & 0xff;
    if ((pos = encode_x8(buffer, size, pos, &tmp6, sizeof(tmp6))) < 0)
    {
        return -1;
    }

    uint16_t tmp7 = obj->pdod << 4 | ((obj->hdop >> 8) & 0x04);
    if ((pos = encode_x16(buffer, size, pos, &tmp7, sizeof(tmp7))) < 0)
    {
        return -1;
    }

    uint8_t tmp8 = obj->hdop & 0xff;
    if ((pos = encode_x8(buffer, size, pos, &tmp8, sizeof(tmp8))) < 0)
    {
        return -1;
    }

    uint16_t tmp9 = (obj->vdop << 4) | (obj->ign_status << 2) | (obj->is_turn_point ? 1 : 0) << 1;
    if ((pos = encode_x16(buffer, size, pos, &tmp9, sizeof(tmp9))) < 0)
    {
        return -1;
    }

    uint16_t tmp10 = obj->hacc;
    if ((pos = encode_x16(buffer, size, pos, &tmp10, sizeof(tmp10))) < 0)
    {
        return -1;
    }

    uint8_t tmp11 = 0x00;
    if ((pos = encode_x8(buffer, size, pos, &tmp11, sizeof(tmp11))) < 0)
    {
        return -1;
    }

    return pos;
}

static int encode_c_gps(unsigned char *buffer, int size, int pos, const void *value, int len)
{

    uint8_t cnt = *(uint8_t *)value;

    if ((pos = encode_x8(buffer, size, pos, &cnt, sizeof(cnt))) < 0)
    {
        return -1;
    }

    if (cnt == 0)
    {
        return pos;
    }

    const gps_t *obj = (const gps_t *)((uint8_t *)value + sizeof(uint8_t));

    for (int i = 0; i < GPS_PACKAGE; i++)
    {
        if ((pos = encode_gps_t(buffer, size, pos, obj + i, sizeof(gps_t))) < 0)
        {
            return -1;
        }
    }

    return pos;
}

#define c_arr(S) c_arr
#define c_str(S) c_str
#define c_gps(S) c_gps
#define s_arr(S) s_arr
#define M(L, R)                                                                         \
    if ((pos = CAT(encode_, L)(buf, size, pos, (const void *)&s->R, sizeof(s->R))) < 0) \
    {                                                                                   \
        return -1;                                                                      \
    }
#define X(S, CMD, META, ...)                                                         \
    static int CAT(encode_, S)(unsigned char *buf, int size, int pos, const void *o) \
    {                                                                                \
        const struct frame_tx_##S##_t *s = (const struct frame_tx_##S##_t *)o;       \
        __VA_ARGS__ return pos;                                                      \
    }
TSP_TX_FRAMES
TSP_FRAME_HEAD
#undef X
#undef M

#define M(L, R, ...)                                                              \
    if ((pos = CAT(decode_, L)(buf, size, pos, (void *)&s->R, sizeof(s->R))) < 0) \
    {                                                                             \
        return -1;                                                                \
    };
#define X(S, CMD, META, ...)                                                         \
    static int CAT(decode_, S)(const unsigned char *buf, int size, int pos, void *o) \
    {                                                                                \
        struct frame_rx_##S##_t *s = (struct frame_rx_##S##_t *)o;                   \
        (void)s;                                                                     \
        __VA_ARGS__ return pos;                                                      \
    }
TSP_RX_FRAMES
TSP_FRAME_HEAD
#undef X
#undef M
#undef c_arr
#undef c_str
#undef c_gps
#undef s_arr

static const struct frame_info_t frame_tx_info[] = {

#define X(name, id, META, ...) [frame_tx_type_##name] = {.desc = #name, .size = sizeof(struct frame_tx_##name##_t), .meta = (META), .cmd = (id), .codec.encode = encode_##name},
    TSP_TX_FRAMES
#undef X
};

static const struct frame_info_t frame_rx_info[] = {
#define X(name, id, META, ...) [frame_rx_type_##name] = {.desc = #name, .size = sizeof(struct frame_rx_##name##_t), .meta = (META), .cmd = (id), .codec.decode = decode_##name},
    TSP_RX_FRAMES
#undef X
};

const struct frame_info_t *frame_tx_get_info(uint8_t type)
{
    if (type <= frame_tx_type_min || type >= frame_tx_type_max)
    {
        return NULL;
    }
    return &frame_tx_info[type];
}

int frame_tx_get_size(uint8_t type)
{
    if (type <= frame_tx_type_min || type >= frame_tx_type_max)
    {
        return 0;
    }
    return (int)(frame_tx_info[type].size + sizeof(struct frame_head_t));
}

static frame_rx_t rx_frame = {0};

// struct frame_tx_pool_node_t {
//     struct frame_tx_t frame;
//     rt_slist_t list;
// };
//
// static rt_slist_t frame_tx_slist = RT_SLIST_OBJECT_INIT(frame_tx_slist);

struct frame_tx_t *frame_tx_create(uint8_t type)
{

    const struct frame_info_t *info = frame_tx_get_info(type);
    if (info == NULL)
    {
        return NULL;
    }

    size_t size = info->size + sizeof(struct frame_head_t);

    return calloc(1, size);

    // LOG_I("create frame, type: %d, desc: %s, size: %d", type, info->desc, size);

    // rt_base_t level = rt_hw_interrupt_disable();

    // if (rt_slist_isempty(&frame_tx_slist)) {

    //    //enable interrupt
    //    rt_hw_interrupt_enable(level);

    //    //内存池为空，直接申请内存
    //    struct frame_tx_pool_node_t *node = (struct frame_tx_pool_node_t *)rt_malloc(sizeof(struct frame_tx_pool_node_t));
    //    if (node == NULL) {
    //        LOG_E("malloc failed, size: %d, desc: %s", size, info->desc);
    //        return NULL;
    //    }

    //    //init frame node
    //    rt_slist_init(&node->list);

    //    node->frame.head.type = type;
    //    memset(&node->frame.value, 0, info->size);

    //    return &node->frame;

    //} else {

    //    //从内存池中取出一个节点
    //    struct frame_tx_pool_node_t *node = rt_slist_first_entry(&frame_tx_slist, struct frame_tx_pool_node_t, list);
    //    rt_slist_remove(&frame_tx_slist, &node->list);

    //    //enable interrupt
    //    rt_hw_interrupt_enable(level);

    //    rt_slist_init(&node->list);

    //    node->frame.head.type = type;
    //    memset(&node->frame.value, 0, info->size);
    //    return &node->frame;
    //}
}

void frame_tx_destroy(struct frame_tx_t *frame)
{
    if (frame == NULL)
    {
        return;
    }

    free(frame);

    // LOG_I("free frame, type: %d, desc: %s", frame->head.type, frame_tx_get_info(frame->head.type)->desc);

    // // disable interrupt
    // rt_base_t level = rt_hw_interrupt_disable();

    // struct frame_tx_pool_node_t *node = rt_container_of(frame, struct frame_tx_pool_node_t, frame);

    // rt_slist_init(&node->list);

    // // max frame pool size is 5
    // unsigned int len = rt_slist_len(&frame_tx_slist);
    // if (len >= 5)
    // {
    //     rt_free(node);
    //     LOG_I("max frame pool size is 5, free frame");
    // }
    // else
    // {
    //     rt_slist_insert(&frame_tx_slist, &node->list);
    // }

    // // enable interrupt
    // rt_hw_interrupt_enable(level);
}

static const char *get_imei(void)
{
    return "862078077190240"; // network.imei;
}

static uint32_t adler32(const uint8_t *buf, uint16_t start, uint16_t len)
{
    uint32_t a = 1, b = 0;
    uint32_t i;
    for (i = start; i < start + len; i++)
    {
        a = (a + buf[i]) % 65521;
        b = (b + a) % 65521;
    }
    return (b << 16) | a;
}

static int check_crc(const uint8_t *data, int size, uint32_t effect)
{

    uint32_t crc; //= adler32(buf->data + 2, effective_len + 22);
    crc = adler32(data, 2, effect + 22);
    uint32_t cmp;

    decode_x32(data, size, (int)effect + 24, &cmp, sizeof(cmp));

    if (crc != cmp)
    {
        LOG_E("check crc error, crc: %x, cmp: %x", crc, cmp);
        return -1;
    }

    return 0;
}

int frame_tx_encode(const struct frame_tx_t *frame, uint8_t *data, int len)
{

    if (frame->head.type <= frame_tx_type_min || frame->head.type >= frame_tx_type_max)
    {
        LOG_E("invalid frame type: %d", frame->head.type);
        return -1;
    }

    int pos = 0, c = 0, m = 0;

    struct frame_info_t *info = (struct frame_info_t *)&frame_tx_info[frame->head.type];

    frame_tx_head_t head = {.start = 0x5555, .seq = frame->head.seq};
    memcpy(head.imei.str, get_imei(), sizeof(head.imei.str));
    head.type = info->meta & META_CONNECT ? 0x01 : (info->meta & META_DEV_RSP ? 0x04 : 0x03);

    if ((pos = encode_head(data, len, pos, &head)) < 0)
    {
        return -1;
    }

    LOG_I("encode frame, desc: %s", info->desc);

    c = pos;

    if (info->meta & META_DATA || info->meta & META_DEV_RSP || info->meta & META_DEV_REQ)
    {
        if ((pos = encode_x16(data, len, pos, &(uint16_t){info->cmd}, sizeof(uint16_t))) < 0)
        {
            return -1;
        }
    }

    if ((pos = info->codec.encode(data, len, pos, &frame->value)) < 0)
    {
        return -1;
    }

    // 填充有效数据长度
    encode_x16(data, len, offsetof(frame_tx_head_t, effect), &(uint16_t){pos - c}, sizeof(uint16_t));

    int crc_pos = pos;
    // crc占位
    if ((pos = encode_x32(data, len, pos, &(uint32_t){0}, sizeof(uint32_t))) < 0)
    {
        return -1;
    }

    if ((m = (int)(pos - offsetof(frame_tx_head_t, type)) % 8) != 0)
    {
        for (int i = 0; i < 8 - m; i++)
        {
            if ((pos = encode_x8(data, len, pos, &(uint8_t){0xff}, sizeof(i))) < 0)
            {
                return -1;
            }
        }
    }

    if ((pos = encode_x16(data, len, pos, &(uint16_t){0xaaaa}, sizeof(uint16_t))) < 0)
    {
        return -1;
    }

    encode_x16(data, len, offsetof(frame_tx_head_t, len), &(uint16_t){pos}, sizeof(uint16_t));

    encode_x32(data, len, crc_pos, &(uint32_t){adler32(data, 2, crc_pos - 2)}, sizeof(uint32_t));

    LOG_HEX(info->desc, 16, data, pos);

    mj_des3_enc(data + offsetof(frame_tx_head_t, type), pos - 2 - offsetof(frame_tx_head_t, type));

    LOG_I("after encrypt");

    LOG_HEX(info->desc, 16, data, pos);

    return pos;
}

int frame_rx_decode(const uint8_t *data, int len)
{

    int pos = 0;
    uint16_t cmd;

    struct frame_rx_head_t head = {0};

    if ((pos = decode_head(data, len, 0, &head)) < 0)
    {
        return -1;
    }

    if (head.start != 0x5555)
    {
        return -1;
    }

    if (head.len > len)
    {
        return 0; // 长度不够，等待下一次
    }

    // check end with 0x00 0xaa 0xaa
    if (data[head.len - 2] != 0xaa || data[head.len - 1] != 0xaa)
    {
        LOG_E("check end failed");
        LOG_HEX("decode", 16, (uint8_t *)data, head.len);
        return -1;
    }

    // decrypt
    mj_des3_dec((uint8_t *)data + offsetof(frame_rx_head_t, type), head.len - 2 - offsetof(frame_rx_head_t, type));

    if ((pos = decode_head(data, len, 0, &head)) < 0)
    {
        return -1;
    }

    if (check_crc(data, len, head.effect) != 0)
    {
        LOG_E("check crc failed");
        LOG_HEX("decode", 16, (uint8_t *)data, head.len);
        return -1;
    }

    LOG_HEX("decode", 16, (uint8_t *)data, head.len > 256 ? 256 : head.len);

    if (head.type != 0x02)
    {
        if ((pos = decode_x16(data, len, pos, &cmd, sizeof(cmd))) < 0)
        {
            return -1;
        }
    }

    const frame_info_t *f = NULL;

    if (head.type == 0x02)
    {
        f = &frame_rx_info[frame_rx_type_connack];
    }
    else if (head.type == 0x03)
    {
        for (int i = frame_rx_type_connack + 1; i < frame_rx_type_srv_rsp_common; i++)
        {
            f = &frame_rx_info[i];
            if (f->meta & META_SRV_REQ && f->cmd == cmd)
            {
                break;
            }
            f = NULL;
        }
    }
    else if (head.type == 0x04)
    {
        for (int i = frame_rx_type_connack + 1; i < frame_rx_type_srv_rsp_common; i++)
        {
            f = &frame_rx_info[i];
            if (f->meta & META_SRV_RSP && f->cmd == cmd)
            {
                break;
            }
            f = NULL;
        }
        if (f == NULL)
        {
            f = &frame_rx_info[frame_rx_type_srv_rsp_common];
        }
    }
    else
    {
        return -1;
    }

    LOG_I("recv frame: %s", f->desc);

    if (f == NULL)
    {
        return -1;
    }

    rx_frame.head.type = (uint8_t)(f - frame_rx_info);
    rx_frame.head.seq = head.seq;
    // decode
    if ((pos = f->codec.decode(data, len, pos, &rx_frame.value)) < 0)
    {
        LOG_E("decode frame failed, type: %d, desc: %s", rx_frame.head.type, f->desc);
        return -1;
    }

    //notify_send(net_notify_type_rx, &(net_notify_value_rx_t){.frame = &rx_frame, .head = &head, .data = data, .pos = pos});

    return 0;
}
